﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace DataGui
{
    public partial class MainWindow : Window
    {
        public static bool SRshow = false;
        string[] safeFilePaths;
        string[] filePaths;

        public MainWindow()
        {
            InitializeComponent();
            safeFilePaths = null;
            filePaths = null;
        }

        private void BopenDatafiles_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            
            dlg.Multiselect = true;
            string x = System.AppDomain.CurrentDomain.BaseDirectory;
            int di = x.LastIndexOf("DataBase");
            dlg.InitialDirectory = x.Substring(0, di) + "DataBase\\DataBase";

            Nullable<bool> result = dlg.ShowDialog();

            if (result == true)
            {
                filePaths = dlg.FileNames;
                safeFilePaths = dlg.SafeFileNames;
                LBfileNames.Items.Clear();
                foreach (String name in safeFilePaths){
                    LBfileNames.Items.Add(name);
                }
                Brun.IsEnabled = true;
            }
        }

        private void Brun_Click(object sender, RoutedEventArgs e)
        {
            if (!validateUserInputData())
            {
                MessageBox.Show("Please insert legal content", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            writeCfgFile();
            clearUserInputReds();
            Running running = new Running(this);
            App.Current.MainWindow = running;
            this.Hide();
            running.Show();
         }

        private void clearUserInputReds()
        {
            TBdevicesNumSSD.Background = Brushes.White;
            TBdevicesNumFC.Background = Brushes.White;
            TBdevicesNumSATA.Background = Brushes.White;
            TbDRTG1.Background = Brushes.White;
            TbDRTG2.Background = Brushes.White;
            TbDRTG3.Background = Brushes.White;
            SRcost.Background = Brushes.White;
            SRfix.Background = Brushes.White;
        }

        private bool validateUserInputData()
        {
            bool valid;

            valid = makeRed(TBdevicesNumSSD,1);
            valid = makeRed(TBdevicesNumFC, 1) & valid;
            valid = makeRed(TBdevicesNumSATA, 1) & valid;
            valid = makeRed(TbDRTG1, 0) & valid;
            valid = makeRed(TbDRTG2, 0) & valid;
            valid = makeRed(TbDRTG3, 0) & valid;
            if ((bool)RBcost.IsChecked)
                valid = makeRed(TBcostSwitch, 1) & valid;

            if (GBSR.IsEnabled)
            {
                valid = makeRed(SRcost, (Convert.ToInt32(SRfix.Text) * Convert.ToInt32(sataCost.Text))) & valid;
                valid = makeRed(SRfix, 0) & valid;
            }

            return valid;
        }

        private bool makeRed(TextBox tb,int limit)
        {
            if (Convert.ToDouble(tb.Text) < limit)
            {
                tb.Background = Brushes.Tomato;
                return false;
            }
            return true;
        }

        private void writeCfgFile()
        {
            TextWriter cfgFile = new StreamWriter("..\\..\\..\\DataBase\\UserInput.cfg");

            cfgFile.WriteLine("#number of paritions in cache");
            cfgFile.WriteLine("nof_partitions=3");
            cfgFile.WriteLine("#size of each partition respectively (in Gigabyte)");
            cfgFile.WriteLine("part_1_size=18");
            cfgFile.WriteLine("part_2_size=10");
            cfgFile.WriteLine("part_3_size=4");
            cfgFile.WriteLine("");
            cfgFile.WriteLine("#luns belonging to each partition respectively (no spaces)");
            cfgFile.WriteLine("part_1_luns=1-2,6");
            cfgFile.WriteLine("part_2_luns=3-4");
            cfgFile.WriteLine("part_3_luns=5");
            cfgFile.WriteLine("/***********************************************************************************************************************************************/");

            cfgFile.WriteLine("#max SSD utilization");
            cfgFile.Write("util_SSD=");
            cfgFile.WriteLine(Math.Round(SlideMaxUtilSSD.Value,2));

            cfgFile.WriteLine("#max FC utilization");
            cfgFile.Write("util_FC=");
            cfgFile.WriteLine(Math.Round(SlideMaxUtilFC.Value,2));

            cfgFile.WriteLine("#max SATA utilization");
            cfgFile.Write("util_SATA=");
            cfgFile.WriteLine(Math.Round(SlideMaxUtilSATA.Value,2));
            
            cfgFile.WriteLine("#group percents");
            cfgFile.Write("group_percents1=");
            cfgFile.WriteLine(rangeSlider1.G1 * 0.01);
            cfgFile.Write("group_percents2=");
            cfgFile.WriteLine(rangeSlider1.G2 * 0.01);
            cfgFile.Write("group_percents3=");
            cfgFile.WriteLine(rangeSlider1.G3 * 0.01);

            cfgFile.WriteLine("#number of luns");
            cfgFile.WriteLine("num_of_luns=1420");

            cfgFile.WriteLine("#number of devices");
            cfgFile.Write("SSD_num=");
            cfgFile.WriteLine(TBdevicesNumSSD.Text);
            cfgFile.Write("FC_num=");
            cfgFile.WriteLine(TBdevicesNumFC.Text);
            cfgFile.Write("SATA_num=");
            cfgFile.WriteLine(TBdevicesNumSATA.Text);

            cfgFile.WriteLine("#DRT for groups in seconds");
            cfgFile.Write("DRT1=");
            cfgFile.WriteLine(Convert.ToDouble(TbDRTG1.Text)*0.001);
            cfgFile.Write("DRT2=");
            cfgFile.WriteLine(Convert.ToDouble(TbDRTG2.Text) * 0.001);
            cfgFile.Write("DRT3=");
            cfgFile.WriteLine(Convert.ToDouble(TbDRTG3.Text) * 0.001);

            cfgFile.WriteLine("#which algo to run 1=Optimal 2=Next 3=Cost");
            cfgFile.Write("whichAlgo=");
            if(RBoptimal.IsChecked == true)
                cfgFile.WriteLine("1");
            else if (RBnext.IsChecked == true)
                cfgFile.WriteLine("2");
            else if(RBcost.IsChecked == true)
                cfgFile.WriteLine("3");
            else cfgFile.WriteLine("0");

            cfgFile.WriteLine("#Cost algo limit");
            cfgFile.Write("exchange_limit=");
            if (RBcost.IsChecked == true)
                cfgFile.WriteLine(TBcostSwitch.Text);
            else cfgFile.WriteLine("0");

            cfgFile.WriteLine("#system cost and fixed amount of sata");
            if (GBSR.IsEnabled)
            {
                cfgFile.WriteLine("system_cost=" + SRcost.Text);
                cfgFile.WriteLine("fix_sata=" + SRfix.Text);
            }
            else
            {
                cfgFile.WriteLine("system_cost=-1");
                cfgFile.WriteLine("fix_sata=35");
            }

            cfgFile.WriteLine("#data file names");
            foreach (String name in safeFilePaths)
            {
                cfgFile.Write("data_file=..\\DataBase\\");
                cfgFile.WriteLine(name);
            }
            
            cfgFile.Close();
            
        }

        private void Bsave_Click(object sender, RoutedEventArgs e)
        {
            if (!validateStorageTableData())
            {
                MessageBox.Show("Please insert legal content", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            writeStorageFile();
            clearStorageTableReds();

            MessageBox.Show("File Saved", "Message", MessageBoxButton.OK, MessageBoxImage.Information);

        }

        private void clearStorageTableReds()
        {
            ssdCapa.Background = Brushes.White;
            ssdCost.Background = Brushes.White;
            ssdEn.Background = Brushes.White;
            ssdOver.Background = Brushes.White;
            ssdRr.Background = Brushes.White;
            ssdWr.Background = Brushes.White;

            fcCapa.Background = Brushes.White;
            fcCost.Background = Brushes.White;
            fcE.Background = Brushes.White;
            fcOver.Background = Brushes.White;
            fcRr.Background = Brushes.White;
            fcWr.Background = Brushes.White;

            sataCapa.Background = Brushes.White;
            sataCost.Background = Brushes.White;
            sataE.Background = Brushes.White;
            sataOver.Background = Brushes.White;
            sataRr.Background = Brushes.White;
            sataWr.Background = Brushes.White;
        }

        private void writeStorageFile()
        {
            TextWriter cfgFile = new StreamWriter("..\\..\\..\\DataBase\\StorageCharacteristics.cfg");

            cfgFile.WriteLine("			#Capacity	#Cost	#Overhead_per_I/O	#R/W_rate	#Energy");
            cfgFile.WriteLine("");
            cfgFile.Write("SSD:\t\t");
            cfgFile.Write(ssdCapa.Text + " \t\t");
            cfgFile.Write(ssdCost.Text + "\t");
            cfgFile.Write(ssdOver.Text + "\t\t\t\t");
            cfgFile.Write(ssdRr.Text + " ");
            cfgFile.Write(ssdWr.Text + " \t");
            cfgFile.WriteLine(ssdEn.Text + "\t\t");

            cfgFile.WriteLine("");
            cfgFile.Write("FC:\t\t\t");
            cfgFile.Write(fcCapa.Text + " \t\t");
            cfgFile.Write(fcCost.Text + "\t\t");
            cfgFile.Write(fcOver.Text + "\t\t\t\t");
            cfgFile.Write(fcRr.Text + " ");
            cfgFile.Write(fcWr.Text + " \t");
            cfgFile.WriteLine(fcE.Text + "\t\t");

            cfgFile.WriteLine("");
            cfgFile.Write("SATA:\t\t");
            cfgFile.Write(sataCapa.Text + " \t\t");
            cfgFile.Write(sataCost.Text + "\t\t");
            cfgFile.Write(sataOver.Text + "\t\t\t\t");
            cfgFile.Write(sataRr.Text + " ");
            cfgFile.Write(sataWr.Text + " \t");
            cfgFile.Write(sataE.Text + "\t\t");

            cfgFile.Close();
        }

        private bool validateStorageTableData()
        {
            bool valid;
            valid = makeRed(ssdCapa, 0) ;
            valid = makeRed(ssdCost, 0) & valid;
            valid = makeRed(ssdEn, 0) & valid;
            valid = makeRed(ssdOver, 0) & valid;
            valid = makeRed(ssdRr, 0) & valid;
            valid = makeRed(ssdWr, 0) & valid;

            valid = makeRed(fcCapa, 0) & valid;
            valid = makeRed(fcCost, 0) & valid;
            valid = makeRed(fcE, 0) & valid;
            valid = makeRed(fcOver, 0) & valid;
            valid = makeRed(fcRr, 0) & valid;
            valid = makeRed(fcWr, 0) & valid;

            valid = makeRed(sataCapa, 0) & valid;
            valid = makeRed(sataCost, 0) & valid;
            valid = makeRed(sataE, 0) & valid;
            valid = makeRed(sataOver, 0) & valid;
            valid = makeRed(sataRr, 0) & valid;
            valid = makeRed(sataWr, 0) & valid;

            return valid;
        }

        private void CBSR_Checked(object sender, RoutedEventArgs e)
        {
            SRshow = true;
            GBSR.IsEnabled = true;
            SRfix.Text = "35";
            SRcost.Text = Convert.ToString((Convert.ToInt32(SRfix.Text) * Convert.ToInt32(sataCost.Text)));
           
        }

        private void CBSR_unChecked(object sender, RoutedEventArgs e)
        {
            SRshow = false;
            GBSR.IsEnabled = false;
            SRcost.Text = "";
            SRfix.Text = "";
            SRfix.Background = Brushes.White;
            SRcost.Background = Brushes.White;
        }

        private void RBcost_Checked(object sender, RoutedEventArgs e)
        {
            TBcostSwitch.IsEnabled = true;
            TBcostSwitch.Text = "1000";
        }

        private void RBcost_Unchecked(object sender, RoutedEventArgs e)
        {
            TBcostSwitch.IsEnabled = true;
            TBcostSwitch.Text = "";
        }
    }
}
